/**
 * Project Name:template-web
 * File Name   :ParamTools.java
 * Package Name:org.cn.template.component.repository
 * Date:2015年9月27日下午3:40:53
 * Copyright (c) 2015, http://my.oschina.net/httpssl All Rights Reserved.
 *
*/

package org.cn.template.component.repository;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.beanutils.BeanMap;

/**
 * ClassName:ParamTools <br/>
 * Function :TODO ADD FUNCTION. <br/>
 * Reason	:TODO ADD REASON. <br/>
 * Date     :2015年9月27日 下午3:40:53 <br/>
 * @author  :http://my.oschina.net/httpssl
 * @email   :491835898@QQ.COM
 * @since   :JDK 1.7
 * @see 	 
 */
public class ParamTools
{
	/**
	 * 将Bean对象转换成Map对象，将忽略掉值为null或size=0的属性
	 * @param obj 对象
	 * @return 若给定对象为null则返回size=0的map对象
	 */
	public static Map<String, Object> toMap(Object obj) {
		Map<String, Object> map = new HashMap<String, Object>();
		if (obj == null) {
			return map;
		}
		BeanMap beanMap = new BeanMap(obj);
		Iterator<String> it = beanMap.keyIterator();
		while (it.hasNext()) {
			String name = it.next();
			Object value = beanMap.get(name);
			// 转换时会将类名也转换成属性，此处去掉
			if (value != null && !name.equals("class")) {
				map.put(name, value);
			}
		}
		return map;
	}

	/**
	 * 该方法将给定的所有对象参数列表转换合并生成一个Map，对于同名属性，依次由后面替换前面的对象属性
	 * @param objs 对象列表
	 * @return 对于值为null的对象将忽略掉
	 */
	public static Map<String, Object> toMap(Object... objs) {
		Map<String, Object> map = new HashMap<String, Object>();
		for (Object object : objs) {
			if (object != null) {
				map.putAll(toMap(object));
			}
		}
		return map;
	}

	/**
	 * 获取接口的泛型类型，如果不存在则返回null
	 * @param clazz
	 * @return
	 */
	public static Class<?> getGenericClass(Class<?> clazz) {
		Type t = clazz.getGenericSuperclass();
		if (t instanceof ParameterizedType) {
			Type[] p = ((ParameterizedType) t).getActualTypeArguments();
			return ((Class<?>) p[0]);
		}
		return null;
	}
	
	public static class UUID_Generator{
		private static boolean IS_THREADLOCALRANDOM_AVAILABLE = false;
		private static Random random;
		private static final long leastSigBits;
		private static final ReentrantLock lock = new ReentrantLock();
		private static long lastTime;

		static {
			try {
				IS_THREADLOCALRANDOM_AVAILABLE = null != UUID_Generator.class.getClassLoader().loadClass(
						"java.util.concurrent.ThreadLocalRandom");
			} catch (ClassNotFoundException e) {
			}

			byte[] seed = new SecureRandom().generateSeed(8);
			leastSigBits = new BigInteger(seed).longValue();
			if (!IS_THREADLOCALRANDOM_AVAILABLE) {
				random = new Random(leastSigBits);
			}
		}

		private UUID_Generator() {
		}

		/**
		 * Create a new random UUID.
		 *
		 * @return the new UUID
		 */
		public static String random() {
			byte[] randomBytes = new byte[16];
			if (IS_THREADLOCALRANDOM_AVAILABLE) {
				java.util.concurrent.ThreadLocalRandom.current().nextBytes(randomBytes);
			} else {
				random.nextBytes(randomBytes);
			}

			long mostSigBits = 0;
			for (int i = 0; i < 8; i++) {
				mostSigBits = (mostSigBits << 8) | (randomBytes[i] & 0xff);
			}
			long leastSigBits = 0;
			for (int i = 8; i < 16; i++) {
				leastSigBits = (leastSigBits << 8) | (randomBytes[i] & 0xff);
			}

			return new UUID(mostSigBits, leastSigBits).toString().replaceAll("-", "");
		}

		/**
		 * Create a new time-based UUID.
		 *
		 * @return the new UUID
		 */
		public static String create() {
			long timeMillis = (System.currentTimeMillis() * 10000) + 0x01B21DD213814000L;

			lock.lock();
			try {
				if (timeMillis > lastTime) {
					lastTime = timeMillis;
				} else {
					timeMillis = ++lastTime;
				}
			} finally {
				lock.unlock();
			}

			// time low
			long mostSigBits = timeMillis << 32;

			// time mid
			mostSigBits |= (timeMillis & 0xFFFF00000000L) >> 16;

			// time hi and version
			mostSigBits |= 0x1000 | ((timeMillis >> 48) & 0x0FFF); // version 1

			return new UUID(mostSigBits, leastSigBits).toString().replaceAll("-", "");
		}
	}
}
